CanvasRenderingContext2D.prototype.drawPeriodicTable = function() {
    var scale = this.canvas.width / 18;
    for (var i = 1; i <= 118; i++) {
        var x, y;
        if (i <= 2) {
            x = i == 1 ? 0 : scale * 17;
            y = 0;
        } else  if (i <= 10) {
            x = (i + (i <= 4 ? -3 : 7)) * scale;
            y = scale;
        } else if (i <= 18) {
            x = (i + (i <= 12 ? -11 : -1)) * scale;
            y = 2 * scale;
        } else if (i <= 36) {
            x = (i - 19) * scale;
            y = 3 * scale;
        } else if (i <= 54) {
            x = (i - 37) * scale;
            y = 4 * scale;
        } else if (i <= 56 || (72 <= i && i <= 86)) {
            x = (i + (i <= 56 ? -55 : -69)) * scale;
            y = 5 * scale;
        } else if (57 <= i && i <= 71) {
            x = (i - 54) * scale;
            y = 8 * scale;
        } else if (i <= 88 || (104 <= i && i <= 118)) {
            x = (i + (i <= 88 ? -87 : -101))  * scale;
            y = 6 * scale;
        } else if (89 <= i && i <= 103) {
            x = (i - 86) * scale;
            y = 9 * scale;
        }
        y += 0.5 * scale;
        this.drawPeriodicSquare(getElementByAtomicNumber(i), x, y, scale);
    }
    this.textAlign = "center";
    this.textBaseline = "middle";
    this.fillStyle = "black";
    this.font = 0.32 * scale + "px serif";
    for (var j = 1; j <= 18; j++) {
        var y = (0.25 + (j != 1 && j != 18 ? 1 : 0) + (3 <= j && j <= 12 ? 2 : 0)) * scale;
        this.fillText(j, (j - 0.5) * scale, y, scale);
    }
    this.fillStyle = "rgb(192,255,255)";
    this.beginPath();
    this.moveTo(2 * scale, 5.5 * scale);
    this.lineTo(3 * scale, 5.5 * scale);
    this.lineTo(3 * scale, 8 * scale);
    this.lineTo(18 * scale, 8 * scale);
    this.lineTo(18 * scale, 8.5 * scale);
    this.lineTo(3 * scale, 8.5 * scale);
    this.lineTo(3 * scale, 10.5 * scale);
    this.lineTo(2 * scale, 10.5 * scale);
    this.fill();
};

CanvasRenderingContext2D.prototype.drawPeriodicSquare = function(e, x, y, scale) {
    this.lineWidth = 0.003 * scale;

    switch (e.group) {
        case 1 : this.fillStyle = "#E6A73A"; break;
        case 2 : this.fillStyle = "#95F144"; break;
        case 17 : this.fillStyle = "#F8FF52"; break;
        case 18 : this.fillStyle = "#BD97C6"; break;
        default : this.fillStyle = "#AAAAAA"; break;
    }
    this.strokeStyle = "#000000";
    this.fillRect(x, y, scale, scale);
    this.strokeRect(x, y, scale, scale);

    this.textAlign = "left";
    this.textBaseline = "top";
    this.fillStyle = "#000000";
    this.font = Math.floor(scale * 0.4) + "px serif";
    this.fillText(e.symbol, x + 0.1 * scale, y + 0.1 * scale, scale);

    this.font = Math.floor(scale * 0.16) + "px serif";
    this.fillText(e.name, x + 0.1 * scale, y + 0.55 * scale, scale);

    this.font = "small-caps " + Math.floor(scale * 0.16) + "px serif";
    this.fillText(e.mass, x + 0.1 * scale, y + 0.75 * scale, scale);

    this.font = "small-caps " + Math.floor(scale * 0.2) + "px serif";
    this.textAlign = "right";
    this.fillText(e.number, x + 0.95 * scale, y + 0.02 * scale, scale);
};

CanvasRenderingContext2D.prototype.drawPeriodicSquare2 = function(e, x, y, scale) {
    var split = String(e.mass).split(".");
    if (split[1].length > 2) {
        e.mass = split[0] + "." + split[1].substring(0,2);
    }
    this.drawPeriodicSquare(e, x, y, scale);
};